home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / progem.arc / sources.arc / GEMC13.C < prev    next >
C/C++ Source or Header  |  1987-10-05  |  14KB  |  539 lines

  1. #include "portab.h"                /* portable coding conv    */
  2. #include "machine.h"                /* machine depndnt conv    */
  3. #include "obdefs.h"                /* object definitions    */
  4. #include "gembind.h"                /* gem binding structs    */
  5. #include "taddr.h"
  6.  
  7. #define    M1_ENTER    0x0000
  8. #define    M1_EXIT        0x0001
  9.  
  10. #define BS    0x0008
  11. #define    TAB    0x0009
  12. #define    CR    0x000D
  13. #define ESC    0x001B
  14. #define    BTAB    0x0f00
  15. #define    UP    0x4800
  16. #define    DOWN    0x5000
  17. #define    DEL    0x5300
  18.                     /* Global variables used by */
  19.                     /* 'mapped' functions        */
  20. MLOCAL    GRECT    br_rect;        /* Current break rectangle  */
  21. MLOCAL    WORD    br_mx, br_my, br_togl;    /* Break mouse posn & flag  */ 
  22. MLOCAL    WORD    fn_obj;            /* Found tabable object        */
  23. MLOCAL    WORD    fn_last;        /* Object tabbing from        */
  24. MLOCAL    WORD    fn_prev;        /* Last EDITABLE obj seen   */
  25. MLOCAL    WORD    fn_dir;            /* 1 = TAB, 0 = BACKTAB        */
  26.  
  27. /************* Utility routines for new forms manager ***************/
  28.  
  29.     VOID
  30. objc_toggle(tree, obj)            /* Reverse the SELECT state */
  31.     LONG    tree;            /* of an object, and redraw */
  32.     WORD    obj;            /* it immediately.        */
  33.     {
  34.     WORD    state, newstate;
  35.     GRECT    root, ob_rect;
  36.  
  37.     objc_xywh(tree, ROOT, &root);
  38.     state = LWGET(OB_STATE(obj));
  39.     newstate = state ^ SELECTED;
  40.     objc_change(tree, obj, 0, root.g_x, root.g_y, 
  41.         root.g_w, root.g_h, newstate, 1);
  42.     }
  43.  
  44.     VOID                /* If the object is not already */
  45. objc_sel(tree, obj)            /* SELECTED, make it so.    */
  46.     LONG    tree;
  47.     WORD    obj;
  48.     {
  49.     if ( !(LWGET(OB_STATE(obj)) & SELECTED) )
  50.         objc_toggle(tree, obj);
  51.     }
  52.  
  53.     VOID                /* If the object is SELECTED,    */
  54. objc_dsel(tree, obj)            /* deselect it.            */
  55.     LONG    tree;
  56.     WORD    obj;
  57.     {
  58.     if (LWGET(OB_STATE(obj)) & SELECTED)
  59.         objc_toggle(tree, obj);
  60.     }
  61.  
  62.     VOID                /* Return the object's GRECT      */
  63. objc_xywh(tree, obj, p)            /* through 'p'            */
  64.     LONG    tree;
  65.     WORD    obj;
  66.     GRECT    *p;
  67.     {
  68.     objc_offset(tree, obj, &p->g_x, &p->g_y);
  69.     p->g_w = LWGET(OB_WIDTH(obj));
  70.     p->g_h = LWGET(OB_HEIGHT(obj));
  71.     }
  72.  
  73.     VOID                /* Non-cursive traverse of an    */
  74. map_tree(tree, this, last, routine)    /* object tree.  This routine    */
  75.     LONG        tree;        /* is described in PRO GEM #5.    */
  76.     WORD        this, last;
  77.     WORD        (*routine)();
  78.     {
  79.     WORD        tmp1;
  80.  
  81.     tmp1 = this;        /* Initialize to impossible value: */
  82.                 /* TAIL won't point to self!       */
  83.                 /* Look until final node, or off   */
  84.                 /* the end of tree           */ 
  85.     while (this != last && this != NIL)
  86.                 /* Did we 'pop' into this node       */
  87.                 /* for the second time?           */
  88.         if (LWGET(OB_TAIL(this)) != tmp1)
  89.             {
  90.             tmp1 = this;    /* This is a new node       */
  91.             this = NIL;
  92.                     /* Apply operation, testing  */
  93.                     /* for rejection of sub-tree */
  94.             if ((*routine)(tree, tmp1))
  95.                 this = LWGET(OB_HEAD(tmp1));
  96.                     /* Subtree path not taken,   */
  97.                     /* so traverse right         */    
  98.             if (this == NIL)
  99.                 this = LWGET(OB_NEXT(tmp1));
  100.             }
  101.         else            /* Revisiting parent:          */
  102.                     /* No operation, move right  */
  103.             {
  104.             tmp1 = this;
  105.             this = LWGET(OB_NEXT(tmp1));
  106.             }
  107.     }
  108.  
  109.     WORD                /* Find the parent object of     */
  110. get_parent(tree, obj)            /* by traversing right until    */
  111.     LONG        tree;        /* we find nodes whose NEXT    */
  112.     WORD        obj;        /* and TAIL links point to     */
  113.     {                /* each other.            */
  114.     WORD        pobj;
  115.  
  116.     if (obj == NIL)
  117.         return (NIL);
  118.     pobj = LWGET(OB_NEXT(obj));
  119.     if (pobj != NIL)
  120.     {
  121.       while( LWGET(OB_TAIL(pobj)) != obj ) 
  122.       {
  123.         obj = pobj;
  124.         pobj = LWGET(OB_NEXT(obj));
  125.       }
  126.     }
  127.     return(pobj);
  128.     } 
  129.  
  130.     WORD
  131. inside(x, y, pt)        /* determine if x,y is in rectangle    */
  132.     WORD        x, y;
  133.     GRECT        *pt;
  134.     {
  135.     if ( (x >= pt->g_x) && (y >= pt->g_y) &&
  136.         (x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) )
  137.         return(TRUE);
  138.     else
  139.         return(FALSE);
  140.     } 
  141.  
  142.     WORD
  143. rc_intersect(p1, p2)        /* compute intersection of two GRECTs    */
  144.     GRECT        *p1, *p2;
  145.     {
  146.     WORD        tx, ty, tw, th;
  147.  
  148.     tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
  149.     th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
  150.     tx = max(p2->g_x, p1->g_x);
  151.     ty = max(p2->g_y, p1->g_y);
  152.     p2->g_x = tx;
  153.     p2->g_y = ty;
  154.     p2->g_w = tw - tx;
  155.     p2->g_h = th - ty;
  156.     return( (tw > tx) && (th > ty) );
  157.     }
  158.  
  159.     VOID
  160. rc_copy(psbox, pdbox)        /* copy source to destination rectangle    */
  161.     GRECT    *psbox;
  162.     GRECT    *pdbox;
  163.     {
  164.     pdbox->g_x = psbox->g_x;
  165.     pdbox->g_y = psbox->g_y;
  166.     pdbox->g_w = psbox->g_w;
  167.     pdbox->g_h = psbox->g_h;
  168.     }
  169.  
  170. /************* "Hot-spot" manager and subroutines  ***************/
  171.  
  172.     WORD
  173. break_x(pxy)
  174.     WORD    *pxy;
  175.     {                /* Breaking object is right of    */
  176.     if (br_mx < pxy[0])        /* mouse.  Reduce width of     */
  177.         {            /* bounding rectangle.        */
  178.         br_rect.g_w = pxy[0] - br_rect.g_x;
  179.         return (TRUE);
  180.         }
  181.     if (br_mx > pxy[2])        /* Object to left.  Reduce width*/
  182.         {            /* and move rect. to right    */
  183.         br_rect.g_w += br_rect.g_x - pxy[2] - 1;
  184.         br_rect.g_x = pxy[2] + 1;
  185.         return (TRUE);
  186.         }
  187.     return (FALSE);            /* Mouse within object segment.    */
  188.     }                /* Break attempt fails.        */
  189.  
  190.     WORD
  191. break_y(pxy)
  192.     WORD    *pxy;
  193.     {
  194.     if (br_my < pxy[1])        /* Object below mouse.  Reduce    */
  195.         {            /* height of bounding rect.    */
  196.         br_rect.g_h = pxy[1] - br_rect.g_y;
  197.         return (TRUE);
  198.         }
  199.     if (br_my > pxy[3])        /* Object above mouse.  Reduce    */
  200.         {            /* height and shift downward.    */
  201.         br_rect.g_h += br_rect.g_y - pxy[3] - 1;
  202.         br_rect.g_y = pxy[3] + 1;
  203.         return (TRUE); 
  204.         }
  205.     /* Emergency escape test! Protection vs. turkeys who nest */
  206.     /* non-selectable objects inside of selectables.          */
  207.     if (br_mx >= pxy[0] && br_mx <= pxy[1])
  208.         {                /* Will X break fail?      */
  209.         br_rect.g_x = br_mx;        /* If so, punt!          */
  210.         br_rect.g_y = br_my;
  211.         br_rect.g_w = br_rect.g_h = 1;
  212.         return (TRUE);
  213.         }
  214.     return (FALSE);
  215.     }
  216.  
  217.     WORD
  218. break_obj(tree, obj)            /* Called once per object to    */
  219.     LONG    tree;            /* check if the bounding rect.    */
  220.     WORD    obj;            /* needs to be modified.    */
  221.     {
  222.     GRECT    s;
  223.     WORD    flags, broken, pxy[4];
  224.  
  225.     objc_xywh(tree, obj, &s);
  226.     grect_to_array(&s, pxy);
  227.     if (!rc_intersect(&br_rect, &s))
  228.         return (FALSE);        /* Trivial rejection case     */
  229.  
  230.     flags = LWGET(OB_FLAGS(obj));    /* Is this object a potential    */
  231.     if (flags & HIDETREE)        /* hot-spot?                 */
  232.         return (FALSE);
  233.     if ( !(flags & SELECTABLE) )
  234.         return (TRUE);
  235.     if (LWGET(OB_STATE(obj)) & DISABLED)
  236.         return (TRUE);
  237.  
  238.     for (broken = FALSE; !broken; ) /* This could take two passes     */
  239.         {            /* if the first break fails.       */
  240.         if (br_togl)
  241.             broken = break_x(pxy);
  242.         else
  243.             broken = break_y(pxy);
  244.         br_togl = !br_togl;
  245.         }
  246.     return (TRUE);
  247.     }
  248.  
  249.     WORD                /* Manages mouse rectangle events */
  250. form_hot(tree, hot_obj, mx, my, rect, mode)
  251.     LONG    tree;
  252.     WORD    hot_obj, mx, my, *mode;
  253.     GRECT    *rect;
  254.     {
  255.     GRECT    root;
  256.     WORD    state;
  257.  
  258.     objc_xywh(tree, ROOT, &root);    /* If there is already a hot-spot */
  259.     if (hot_obj != NIL)        /* turn it off.              */
  260.         objc_toggle(tree, hot_obj);
  261.  
  262.     if (!(inside(mx, my, &root)) )    /* Mouse has moved outside of       */
  263.         {            /* the dialog.  Wait for return.  */
  264.         *mode = M1_ENTER;
  265.         rc_copy(&root, rect);
  266.         return (NIL);
  267.         }
  268.                     /* What object is mouse over?      */
  269.                     /* (Hit is guaranteed.)           */
  270.     hot_obj = objc_find(tree, ROOT, MAX_DEPTH, mx, my);
  271.                     /* Is this object a hot-spot?      */
  272.     state = LWGET(OB_STATE(hot_obj));
  273.     if (LWGET(OB_FLAGS(hot_obj)) & SELECTABLE)
  274.     if ( !(state & DISABLED) )
  275.         {            /* Yes!  Set up wait state.      */
  276.         *mode = M1_EXIT;
  277.         objc_xywh(tree, hot_obj, rect);
  278.         if (state & SELECTED)    /* But only toggle if it's not      */
  279.             return (NIL);    /* already SELECTED!          */
  280.         else
  281.             {
  282.             objc_toggle(tree, hot_obj);
  283.             return (hot_obj);
  284.             }
  285.         }
  286.  
  287.     rc_copy(&root, &br_rect);    /* No hot object, so compute    */
  288.     br_mx = mx;            /* mouse bounding rectangle.    */
  289.     br_my = my;
  290.     br_togl = 0;
  291.     map_tree(tree, ROOT, NIL, break_obj);
  292.     rc_copy(&br_rect, rect);    /* Then return to wait state.    */
  293.     *mode = M1_EXIT;
  294.     return (NIL);
  295.     }
  296.  
  297. /************* Keyboard manager and subroutines ***************/
  298.  
  299.     WORD
  300. find_def(tree, obj)        /* Check if the object is DEFAULT    */
  301.     LONG    tree;
  302.     WORD    obj;
  303.     {            /* Is sub-tree hidden?            */
  304.     if (HIDETREE & LWGET(OB_FLAGS(obj)))
  305.         return (FALSE);
  306.                 /* Must be DEFAULT and not DISABLED    */
  307.     if (DEFAULT & LWGET(OB_FLAGS(obj)))
  308.     if ( !(DISABLED & LWGET(OB_STATE(ob